import * as compiler from '@vue/compiler-sfc';
import { ComponentProp, ComponentEvent, ComponentSlot, ComponentEventArgument, ComponentSlotBinding } from '../../core/types';
import { CommentUtils } from './CommentUtils';
import { TypeUtils } from './TypeUtils';

/**
 * 组件属性提取工具类
 * 使用compiler-sfc解析Vue组件的属性
 */
export class ComponentPropertyExtractor {
  /**
   * 提取组件Props
   * @param descriptor Vue SFC描述符
   * @param scriptContent 脚本内容
   * @returns 组件Props列表
   */
  public static extractProps(descriptor: compiler.SFCDescriptor): ComponentProp[] {
    const props: ComponentProp[] = [];
    const scriptContent = descriptor.script?.content || descriptor.scriptSetup?.content || '';
    
    // 检查withDefaults和defineProps组合
    const withDefaultsMatch = scriptContent.match(/withDefaults\s*\(\s*defineProps\s*<([^>]+)>\(\)\s*,\s*(\{[^}]+\})\s*\)/s);
    if (withDefaultsMatch) {
      const propsTypeContent = withDefaultsMatch[1];
      const defaultsContent = withDefaultsMatch[2];
      
      // 解析属性类型
      const propMatches = [...propsTypeContent.matchAll(/(\w+)\s*(\?)?:\s*([^;,]+)/g)];
      
      for (const match of propMatches) {
        const propName = match[1];
        const isOptional = match[2] === '?';
        const propType = match[3].trim();
        
        // 查找默认值
        const defaultMatch = new RegExp(`${propName}\\s*:\\s*([^,}]+)`, 'g').exec(defaultsContent);
        const defaultValue = defaultMatch ? defaultMatch[1].trim() : undefined;
        
        // 从类型中提取可能的枚举值
        const values = TypeUtils.extractEnumValuesFromTypeString(propType);
        
        props.push({
          name: propName,
          type: propType,
          description: this.findPropDescription(propName, scriptContent),
          defaultValue: defaultValue,
          required: !isOptional && !defaultValue,
          values: values,
        });
      }
      
      return props;
    }
    
    // 检查defineProps<Type>()语法
    const definePropsTypeMatch = scriptContent.match(/defineProps\s*<([^>]+)>\s*\(\)/s);
    if (definePropsTypeMatch) {
      const propsTypeContent = definePropsTypeMatch[1];
      
      // 解析属性类型
      const propMatches = [...propsTypeContent.matchAll(/(\w+)\s*(\?)?:\s*([^;,]+)/g)];
      
      for (const match of propMatches) {
        const propName = match[1];
        const isOptional = match[2] === '?';
        const propType = match[3].trim();
        
        // 从类型中提取可能的枚举值
        const values = TypeUtils.extractEnumValuesFromTypeString(propType);
        
        props.push({
          name: propName,
          type: propType,
          description: this.findPropDescription(propName, scriptContent),
          required: !isOptional,
          values: values,
        });
      }
      
      return props;
    }
    
    // 检查defineProps({})语法
    const definePropsObjectMatch = scriptContent.match(/defineProps\s*\(\s*(\{[^}]+\})\s*\)/s);
    if (definePropsObjectMatch) {
      const propsObjectContent = definePropsObjectMatch[1];
      
      // 解析属性对象
      const propMatches = [...propsObjectContent.matchAll(/(\w+)\s*:\s*(?:\{([^}]+)\}|([^,]+))/gs)];
      
      for (const match of propMatches) {
        const propName = match[1];
        const propConfig = match[2] || match[3];
        
        if (!propConfig) continue;
        
        let type = 'any';
        let required = false;
        let defaultValue: string | undefined;
        
        // 如果是对象配置
        if (match[2]) {
          // 提取类型
          const typeMatch = propConfig.match(/type\s*:\s*([^,]+)/);
          if (typeMatch) {
            type = typeMatch[1].trim();
          }
          
          // 提取是否必填
          const requiredMatch = propConfig.match(/required\s*:\s*(true|false)/);
          if (requiredMatch) {
            required = requiredMatch[1] === 'true';
          }
          
          // 提取默认值
          const defaultMatch = propConfig.match(/default\s*:\s*(?:function\s*\(\)\s*\{\s*return\s*([^;]+);\s*\}|([^,]+))/);
          if (defaultMatch) {
            defaultValue = (defaultMatch[1] || defaultMatch[2]).trim();
          }
        } else {
          // 如果是简单类型
          type = propConfig.trim();
        }
        
        // 根据类型名称获取实际的类型字符串
        if (type.includes('String')) type = 'string';
        else if (type.includes('Number')) type = 'number';
        else if (type.includes('Boolean')) type = 'boolean';
        else if (type.includes('Array')) type = 'array';
        else if (type.includes('Object')) type = 'object';
        else if (type.includes('Function')) type = 'function';
        
        props.push({
          name: propName,
          type: type,
          description: this.findPropDescription(propName, scriptContent),
          defaultValue: defaultValue,
          required: required,
          values: [],
        });
      }
      
      return props;
    }
    
    // Vue2风格的props (options API)
    const optionsPropsMatch = scriptContent.match(/props\s*:\s*\{([^}]+)\}/s);
    if (optionsPropsMatch) {
      const propsObject = optionsPropsMatch[1];
      
      // 提取属性定义
      const propDefinitions = [...propsObject.matchAll(/(\w+)\s*:\s*(?:(\w+)|(\{[\s\S]*?\}))/g)];
      
      for (const definition of propDefinitions) {
        const propName = definition[1];
        const simpleType = definition[2]; // 如果是简单类型，例如 propName: String
        const complexType = definition[3]; // 如果是对象配置，例如 propName: { type: String, required: true }
        
        let type = 'any';
        let required = false;
        let defaultValue: string | undefined;
        let values: string[] = [];
        
        if (simpleType) {
          // 处理简单类型
          type = this.mapVueTypeToString(simpleType);
        } else if (complexType) {
          // 处理对象配置
          // 提取类型
          const typeMatch = complexType.match(/type\s*:\s*(\w+)/);
          if (typeMatch) {
            type = this.mapVueTypeToString(typeMatch[1]);
          }
          
          // 提取是否必填
          const requiredMatch = complexType.match(/required\s*:\s*(true|false)/);
          if (requiredMatch) {
            required = requiredMatch[1] === 'true';
          }
          
          // 提取默认值
          const defaultMatch = complexType.match(/default\s*:\s*(?:function\s*\(\)\s*\{\s*return\s*([^;]+);\s*\}|([^,]+))/);
          if (defaultMatch) {
            defaultValue = (defaultMatch[1] || defaultMatch[2]).trim();
          }
          
          // 提取验证函数中可能的枚举值
          const validatorMatch = complexType.match(/validator\s*:\s*function\s*\([^)]*\)\s*\{[\s\S]*?return\s*\[([^\]]+)\]/);
          if (validatorMatch) {
            const valuesString = validatorMatch[1];
            const valueMatches = [...valuesString.matchAll(/['"]([^'"]+)['"]/g)];
            
            values = valueMatches.map(match => match[1]);
          }
        }
        
        // 从注释中查找类型信息
        const propComment = this.findPropComment(propName, scriptContent);
        const commentType = propComment ? CommentUtils.extractPropType(propComment) : undefined;
        
        // 合并类型信息
        const finalType = TypeUtils.mergeTypes(type, commentType);
        
        // 从注释中查找可能的枚举值
        const commentValues = propComment ? CommentUtils.extractEnumValues(propComment) : [];
        
        // 合并枚举值
        if (commentValues.length > 0) {
          values = [...new Set([...values, ...commentValues])];
        }
        
        props.push({
          name: propName,
          type: finalType,
          description: this.findPropDescription(propName, scriptContent),
          defaultValue: defaultValue,
          required: required,
          values: values,
        });
      }
    }
    
    return props;
  }

  /**
   * 提取组件事件
   * @param descriptor Vue SFC描述符
   * @returns 组件事件列表
   */
  public static extractEvents(descriptor: compiler.SFCDescriptor): ComponentEvent[] {
    const events: ComponentEvent[] = [];
    const scriptContent = descriptor.script?.content || descriptor.scriptSetup?.content || '';
    const templateContent = descriptor.template?.content || '';
    
    // 查找emit定义 (Composition API 类型形式)
    const defineEmitsMatch = scriptContent.match(/defineEmits\s*<\{([^}]+)\}>\s*\(\)/s);
    if (defineEmitsMatch) {
      const emitsContent = defineEmitsMatch[1];
      const emitMatches = [...emitsContent.matchAll(/\(e\s*:\s*['"]([^'"]+)['"]\s*(?:,\s*([^)]+))?\)\s*=>\s*void/g)];
      
      for (const match of emitMatches) {
        const eventName = match[1];
        const argsContent = match[2];
        const args: ComponentEventArgument[] = [];
        
        if (argsContent) {
          const argMatches = [...argsContent.matchAll(/(\w+)\s*:\s*([^,]+)/g)];
          for (const argMatch of argMatches) {
            args.push({
              name: argMatch[1],
              type: argMatch[2].trim(),
              description: '',
            });
          }
        }
        
        events.push({
          name: eventName,
          description: this.findEventDescription(eventName, scriptContent),
          arguments: args,
        });
      }
      
      return events;
    }
    
    // 查找defineEmits数组语法 (Composition API 数组形式)
    const defineEmitsArrayMatch = scriptContent.match(/defineEmits\s*\(\s*\[((?:'[^']+'\s*,?\s*|"[^"]+"\s*,?\s*)+)\]\s*\)/s);
    if (defineEmitsArrayMatch) {
      const emitsArray = defineEmitsArrayMatch[1];
      const eventMatches = [...emitsArray.matchAll(/['"]([^'"]+)['"]/g)];
      
      for (const match of eventMatches) {
        const eventName = match[1];
        
        events.push({
          name: eventName,
          description: this.findEventDescription(eventName, scriptContent),
          arguments: [],
        });
      }
      
      return events;
    }
    
    // 查找emits选项 (Options API)
    const optionsEmitsMatch = scriptContent.match(/emits\s*:\s*\[((?:'[^']+'\s*,?\s*|"[^"]+"\s*,?\s*)+)\]/s);
    if (optionsEmitsMatch) {
      const emitsArray = optionsEmitsMatch[1];
      const eventMatches = [...emitsArray.matchAll(/['"]([^'"]+)['"]/g)];
      
      for (const match of eventMatches) {
        const eventName = match[1];
        
        events.push({
          name: eventName,
          description: this.findEventDescription(eventName, scriptContent),
          arguments: [],
        });
      }
    }
    
    // 查找模板中的emit调用
    if (templateContent) {
      // Vue3: $emit
      const emitMatches = [...templateContent.matchAll(/\$emit\s*\(\s*['"]([^'"]+)['"]/g)];
      
      for (const match of emitMatches) {
        const eventName = match[1];
        
        // 检查事件是否已存在
        const existingEvent = events.find(e => e.name === eventName);
        if (!existingEvent) {
          events.push({
            name: eventName,
            description: this.findEventDescription(eventName, scriptContent),
            arguments: [],
          });
        }
      }
      
      // Vue2: this.$emit
      const thisEmitMatches = [...scriptContent.matchAll(/this\.\$emit\s*\(\s*['"]([^'"]+)['"]/g)];
      
      for (const match of thisEmitMatches) {
        const eventName = match[1];
        
        // 检查事件是否已存在
        const existingEvent = events.find(e => e.name === eventName);
        if (!existingEvent) {
          // 查找脚本中对该事件的定义，以获取参数信息
          const eventComment = this.findEventComment(eventName, scriptContent);
          const params = eventComment ? CommentUtils.extractParams(eventComment) : [];
          
          const args: ComponentEventArgument[] = params.map(param => ({
            name: param.name,
            type: param.type || 'any',
            description: param.description,
          }));
          
          events.push({
            name: eventName,
            description: eventComment ? CommentUtils.extractDescription(eventComment) : '',
            arguments: args,
          });
        }
      }
    }
    
    return events;
  }

  /**
   * 提取组件插槽
   * @param descriptor Vue SFC描述符
   * @returns 组件插槽列表
   */
  public static extractSlots(descriptor: compiler.SFCDescriptor): ComponentSlot[] {
    const slots: ComponentSlot[] = [];
    
    if (!descriptor.template?.content) {
      return slots;
    }
    
    const templateContent = descriptor.template.content;
    
    // 查找命名插槽
    const namedSlotMatches = [...templateContent.matchAll(/<slot\s+name=(['"])([^'"]+)\1[^>]*>/g)];
    
    for (const match of namedSlotMatches) {
      const slotName = match[2];
      const slotTag = match[0];
      
      // 检查插槽是否已存在
      const existingSlot = slots.find(s => s.name === slotName);
      if (!existingSlot) {
        // 查找slot上的属性，它们可能是绑定变量
        const bindingMatches = [...slotTag.matchAll(/\s+:([^=]+)=(['"])([^'"]+)\2/g)];
        const bindings: ComponentSlotBinding[] = [];
        
        for (const bindingMatch of bindingMatches) {
          bindings.push({
            name: bindingMatch[1],
            type: 'any', // 默认类型
            description: '',
          });
        }
        
        slots.push({
          name: slotName,
          description: this.findSlotDescription(slotName, templateContent),
          bindings: bindings,
        });
      }
    }
    
    // 查找Vue 3的v-slot语法
    const vSlotMatches = [...templateContent.matchAll(/<template\s+v-slot:([^=>\s]+)[^>]*>/g)];
    
    for (const match of vSlotMatches) {
      const slotName = match[1];
      
      // 检查插槽是否已存在
      const existingSlot = slots.find(s => s.name === slotName);
      if (!existingSlot) {
        slots.push({
          name: slotName,
          description: '',
          bindings: [],
        });
      }
    }
    
    // 查找默认插槽
    const defaultSlotMatch = templateContent.match(/<slot\s+[^>]*>/);
    if (defaultSlotMatch && !slots.find(s => s.name === 'default')) {
      const slotTag = defaultSlotMatch[0];
      
      // 查找slot上的属性，它们可能是绑定变量
      const bindingMatches = [...slotTag.matchAll(/\s+:([^=]+)=(['"])([^'"]+)\2/g)];
      const bindings: ComponentSlotBinding[] = [];
      
      for (const bindingMatch of bindingMatches) {
        bindings.push({
          name: bindingMatch[1],
          type: 'any',
          description: '',
        });
      }
      
      slots.push({
        name: 'default',
        description: this.findSlotDescription('default', templateContent),
        bindings: bindings,
      });
    }
    
    return slots;
  }

  /**
   * 查找属性注释
   * @param propName 属性名
   * @param scriptContent 脚本内容
   * @returns 属性注释
   */
  private static findPropComment(propName: string, scriptContent: string): string | null {
    // 查找属性的注释
    const propCommentPattern = new RegExp(`\\/\\*\\*((?:[^*]|\\*[^/])*)\\*\\/\\s*(?:${propName}\\s*[?:]|${propName}\\s*\\(|${propName}:|${propName}\\s*=)`, 's');
    const commentMatch = propCommentPattern.exec(scriptContent);
    
    if (commentMatch) {
      return commentMatch[1];
    }
    
    return null;
  }

  /**
   * 查找属性描述
   * @param propName 属性名
   * @param scriptContent 脚本内容
   * @returns 属性描述
   */
  private static findPropDescription(propName: string, scriptContent: string): string {
    const propComment = this.findPropComment(propName, scriptContent);
    return propComment ? CommentUtils.extractDescription(propComment) : '';
  }

  /**
   * 查找事件注释
   * @param eventName 事件名
   * @param scriptContent 脚本内容
   * @returns 事件注释
   */
  private static findEventComment(eventName: string, scriptContent: string): string | null {
    // 查找事件的注释，通常在$emit调用前
    const eventCommentPattern = new RegExp(`\\/\\*\\*((?:[^*]|\\*[^/])*)\\*\\/[\\s\\S]*?\\$emit\\s*\\(\\s*['"]${eventName}['"]`, 's');
    const commentMatch = eventCommentPattern.exec(scriptContent);
    
    if (commentMatch) {
      return commentMatch[1];
    }
    
    return null;
  }

  /**
   * 查找事件描述
   * @param eventName 事件名
   * @param scriptContent 脚本内容
   * @returns 事件描述
   */
  private static findEventDescription(eventName: string, scriptContent: string): string {
    const eventComment = this.findEventComment(eventName, scriptContent);
    return eventComment ? CommentUtils.extractDescription(eventComment) : '';
  }

  /**
   * 查找插槽描述
   * @param slotName 插槽名
   * @param templateContent 模板内容
   * @returns 插槽描述
   */
  private static findSlotDescription(slotName: string, templateContent: string): string {
    // 查找slot标签前的注释
    const slotPattern = slotName === 'default' 
      ? /(<!--((?:[^-]|(?:-(?!->)))*)--->)?\s*<slot\s+[^>]*>/
      : new RegExp(`(<!--((?:[^-]|(?:-(?!->)))*)--->)?\\s*<slot\\s+name=['"']${slotName}['"'][^>]*>`, 's');
    
    const slotMatch = slotPattern.exec(templateContent);
    
    if (slotMatch && slotMatch[1]) {
      // 提取注释内容
      const comment = slotMatch[2];
      if (comment) {
        return comment.trim();
      }
    }
    
    return '';
  }

  /**
   * 映射Vue类型声明到字符串类型
   * @param vueType Vue类型（String, Number等）
   * @returns 映射后的类型字符串
   */
  private static mapVueTypeToString(vueType: string): string {
    switch (vueType.trim()) {
      case 'String': return 'string';
      case 'Number': return 'number';
      case 'Boolean': return 'boolean';
      case 'Array': return 'array';
      case 'Object': return 'object';
      case 'Function': return 'function';
      case 'Date': return 'date';
      case 'Symbol': return 'symbol';
      default: return vueType.toLowerCase();
    }
  }
} 